/**
 * 基于uniapp的请求工具类
 * 支持请求拦截、响应拦截、错误处理、token管理等功能
 */

// 请求基础配置
const config = {
	// 基础URL，根据环境切换
	baseURL: process.env.NODE_ENV === 'development' 
		? '/dyapi'  // 开发环境
		: 'https://api.example.com',     // 生产环境
	
	// 请求超时时间（毫秒）
	timeout: 10000,
	
	// 默认请求头
	header: {
		'Content-Type': 'application/json'
	}
}

// 请求拦截器
const requestInterceptor = (options) => {
	// 添加token到请求头
	const token = uni.getStorageSync('token')
	if (token) {
		options.header = {
			...options.header,
			'token': `${token}`
		}
	}
	
	// 显示加载提示（可选）
	if (options.loading !== false) {
		uni.showLoading({
			title: options.loadingText || '加载中...',
			mask: true
		})
	}
	
	return options
}

// 响应拦截器
const responseInterceptor = (response, options) => {
	// 隐藏加载提示
	if (options.loading !== false) {
		uni.hideLoading()
	}
	
	const { statusCode, data } = response
	
	// HTTP状态码处理
	if (statusCode === 200) {
		// 业务状态码处理（根据后端接口规范调整）
		if (data.code === 200 || data.code === 0) {
			// 成功
			return Promise.resolve(data)
		} else if (data.code === 401) {
			// token过期或未登录
			handleUnauthorized()
			return Promise.reject(new Error(data.message || '未登录或登录已过期'))
		} else if (data.code === 400 && Array.isArray(data.data)) {
			// 参数校验失败，返回详细的错误信息，不显示toast，由调用方处理
			const error = new Error(data.message || '参数校验失败')
			error.validationErrors = data.data // 将校验错误信息附加到error对象上
			return Promise.reject(error)
		} else {
			// 业务错误
			const errorMsg = data.message || data.msg || '请求失败'
			uni.showToast({
				title: errorMsg,
				icon: 'none',
				duration: 2000
			})
			return Promise.reject(new Error(errorMsg))
		}
	} else if (statusCode === 401) {
		// 未授权
		handleUnauthorized()
		return Promise.reject(new Error('未登录或登录已过期'))
	} else if (statusCode === 403) {
		// 禁止访问
		uni.showToast({
			title: '没有权限访问',
			icon: 'none'
		})
		return Promise.reject(new Error('没有权限访问'))
	} else if (statusCode === 404) {
		// 接口不存在
		uni.showToast({
			title: '接口不存在',
			icon: 'none'
		})
		return Promise.reject(new Error('接口不存在'))
	} else if (statusCode >= 500) {
		// 服务器错误
		uni.showToast({
			title: '服务器错误，请稍后重试',
			icon: 'none'
		})
		return Promise.reject(new Error('服务器错误'))
	} else {
		// 其他错误
		uni.showToast({
			title: '请求失败',
			icon: 'none'
		})
		return Promise.reject(new Error('请求失败'))
	}
}

// 处理未授权（token过期）
const handleUnauthorized = () => {
	// 清除本地存储的token和用户信息
	uni.removeStorageSync('token')
	uni.removeStorageSync('userInfo')
	
	// 跳转到登录页
	const pages = getCurrentPages()
	const currentPage = pages[pages.length - 1]
	const route = currentPage.route
	
	// 如果当前不在登录页，则跳转到登录页
	if (route !== 'pages/login/index') {
		uni.reLaunch({
			url: '/pages/login/index'
		})
	}
}

// 错误处理
const errorHandler = (error, options) => {
	// 隐藏加载提示
	if (options.loading !== false) {
		uni.hideLoading()
	}
	
	let errorMsg = '网络错误，请检查网络连接'
	
	if (error.errMsg) {
		if (error.errMsg.includes('timeout')) {
			errorMsg = '请求超时，请稍后重试'
		} else if (error.errMsg.includes('fail')) {
			errorMsg = '网络请求失败，请检查网络连接'
		}
	}
	
	// 不显示toast的情况（由调用方自己处理）
	if (options.showError !== false) {
		uni.showToast({
			title: errorMsg,
			icon: 'none',
			duration: 2000
		})
	}
	
	return Promise.reject(error)
}

/**
 * 请求方法
 * @param {Object} options 请求配置
 * @param {String} options.url 请求地址
 * @param {String} options.method 请求方法，默认GET
 * @param {Object} options.data 请求数据
 * @param {Object} options.header 请求头
 * @param {Boolean} options.loading 是否显示加载提示，默认true
 * @param {String} options.loadingText 加载提示文字
 * @param {Boolean} options.showError 是否显示错误提示，默认true
 * @returns {Promise}
 */
const request = (options = {}) => {
	return new Promise((resolve, reject) => {
		// 构建完整URL（使用相对路径，让代理生效）
		const finalUrl = options.url.startsWith('http://') || options.url.startsWith('https://')
			? options.url 
			: config.baseURL + options.url
		
		// 合并配置
		const requestOptions = {
			url: finalUrl,
			method: options.method || 'GET',
			data: options.data || {},
			header: {
				...config.header,
				...options.header
			},
			timeout: options.timeout || config.timeout,
			loading: options.loading !== undefined ? options.loading : true,
			loadingText: options.loadingText,
			showError: options.showError !== undefined ? options.showError : true
		}
		
		// 请求拦截
		const interceptedOptions = requestInterceptor(requestOptions)
		
		// 发起请求
		uni.request({
			url: interceptedOptions.url,
			method: interceptedOptions.method,
			data: interceptedOptions.data,
			header: interceptedOptions.header,
			timeout: interceptedOptions.timeout,
			success: (response) => {
				// 响应拦截
				responseInterceptor(response, interceptedOptions)
					.then(resolve)
					.catch(reject)
			},
			fail: (error) => {
				// 错误处理
				errorHandler(error, interceptedOptions)
					.catch(reject)
			}
		})
	})
}

/**
 * GET请求
 * @param {String} url 请求地址
 * @param {Object} params 请求参数
 * @param {Object} options 其他配置
 * @returns {Promise}
 */
const get = (url, params = {}, options = {}) => {
	return request({
		url,
		method: 'GET',
		data: params,
		...options
	})
}

/**
 * POST请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} options 其他配置
 * @returns {Promise}
 */
const post = (url, data = {}, options = {}) => {
	return request({
		url,
		method: 'POST',
		data,
		...options
	})
}

/**
 * PUT请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} options 其他配置
 * @returns {Promise}
 */
const put = (url, data = {}, options = {}) => {
	return request({
		url,
		method: 'PUT',
		data,
		...options
	})
}

/**
 * DELETE请求
 * @param {String} url 请求地址
 * @param {Object} params 请求参数
 * @param {Object} options 其他配置
 * @returns {Promise}
 */
const del = (url, params = {}, options = {}) => {
	return request({
		url,
		method: 'DELETE',
		data: params,
		...options
	})
}

/**
 * 文件上传
 * @param {String} url 上传地址
 * @param {String} filePath 文件路径
 * @param {String} name 文件对应的key
 * @param {Object} formData 额外的表单数据
 * @param {Function} onProgressUpdate 上传进度回调
 * @returns {Promise}
 */
const upload = (url, filePath, name = 'file', formData = {}, onProgressUpdate = null) => {
	return new Promise((resolve, reject) => {
		// 添加token
		const token = uni.getStorageSync('token')
		const header = {}
		if (token) {
			header['Authorization'] = `Bearer ${token}`
		}
		
		uni.showLoading({
			title: '上传中...',
			mask: true
		})
		
		// 构建完整URL（使用相对路径，让代理生效）
		const finalUploadUrl = url.startsWith('http://') || url.startsWith('https://')
			? url 
			: config.baseURL + url
		
		uni.uploadFile({
			url: finalUploadUrl,
			filePath,
			name,
			formData,
			header,
			success: (response) => {
				uni.hideLoading()
				try {
					const data = JSON.parse(response.data)
					if (data.code === 200 || data.code === 0) {
						resolve(data)
					} else {
						uni.showToast({
							title: data.message || '上传失败',
							icon: 'none'
						})
						reject(new Error(data.message || '上传失败'))
					}
				} catch (e) {
					uni.showToast({
						title: '上传失败',
						icon: 'none'
					})
					reject(new Error('上传失败'))
				}
			},
			fail: (error) => {
				uni.hideLoading()
				uni.showToast({
					title: '上传失败，请检查网络',
					icon: 'none'
				})
				reject(error)
			},
			progress: (progress) => {
				if (onProgressUpdate && typeof onProgressUpdate === 'function') {
					onProgressUpdate(progress)
				}
			}
		})
	})
}

// 导出
export default {
	request,
	get,
	post,
	put,
	delete: del,
	upload,
	config
}
